package com.qcrud.core.paging;

import lombok.Setter;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;

@Setter
public class Paging<T> implements Serializable {

    /**
     * 查询数据列表
     */
    protected List<T> records = Collections.emptyList();
    /**
     * 总数
     */
    protected long total = 0;
    /**
     * 每页显示条数，默认 10
     */
    protected long size = 10;
    /**
     * 当前页
     */
    protected long current = 1;
    /**
     * 自动优化 COUNT SQL
     */
    protected boolean optimizeCountSql = true;
    /**
     * 是否进行 count 查询
     */
    protected boolean searchCount = true;

    public Paging() {
    }

    /**
     * 分页构造函数
     *
     * @param current 当前页
     * @param size    每页显示条数
     */
    public Paging(long current, long size) {
        this(current, size, 0);
    }

    public Paging(long current, long size, long total) {
        this(current, size, total, true);
    }

    public Paging(long current, long size, boolean searchCount) {
        this(current, size, 0, searchCount);
    }

    public Paging(long current, long size, long total, boolean searchCount) {
        if (current > 1) {
            this.current = current;
        }
        this.size = size;
        this.total = total;
        this.searchCount = searchCount;
    }

    /**
     * 计算当前分页偏移量
     */
    public long offset() {
        long current = getCurrent();
        if (current <= 1L) {
            return 0L;
        }
        return Math.max((current - 1) * getSize(), 0L);
    }

    /**
     * 当前分页总页数
     */
    public long getPages() {
        if (getSize() == 0) {
            return 0L;
        }
        long pages = getTotal() / getSize();
        if (getTotal() % getSize() != 0) {
            pages++;
        }
        return pages;
    }

    /**
     * 是否存在上一页
     *
     * @return true / false
     */
    public boolean hasPrevious() {
        return this.current > 1;
    }

    /**
     * 是否存在下一页
     *
     * @return true / false
     */
    public boolean hasNext() {
        return this.current < this.getPages();
    }

    public List<T> getRecords() {
        return this.records;
    }

    public Paging<T> setRecords(List<T> records) {
        this.records = records;
        return this;
    }

    public long getTotal() {
        return this.total;
    }

    public Paging<T> setTotal() {
        this.total = total;
        return this;
    }

    public long getSize() {
        return this.size;
    }

    public Paging<T> setSize(long size) {
        this.size = size;
        return this;
    }

    public long getCurrent() {
        return this.current;
    }

    public Paging<T> setCurrent(long current) {
        this.current = current;
        return this;
    }


    /* --------------- 以下为静态构造方式 --------------- */
    public static <T> Paging<T> of(long current, long size) {
        return of(current, size, 0);
    }

    public static <T> Paging<T> of(long current, long size, long total) {
        return of(current, size, total, true);
    }

    public static <T> Paging<T> of(long current, long size, boolean searchCount) {
        return of(current, size, 0, searchCount);
    }

    public static <T> Paging<T> of(long current, long size, long total, boolean searchCount) {
        return new Paging<>(current, size, total, searchCount);
    }

    public boolean optimizeCountSql() {
        return optimizeCountSql;
    }

    public boolean searchCount() {
        if (total < 0) {
            return false;
        }
        return searchCount;
    }
}
